#include "com_service_provider.h"

#include <comutil.h>

#include "npapi.h"
#include "npfunctions.h"
#include "npruntime.h"

#include "common.h"


extern NPNetscapeFuncs* browserFuncs;

HRESULT STDMETHODCALLTYPE ServiceStub::QueryService(/* [in] */ REFGUID guidService, /* [in] */ REFIID riid, /* [out] */ void** ppvObject)
{
#ifdef _DEBUG_
    TRACE("IEDocument::QueryService");
	if (IsEqualIID(riid, __uuidof(IHTMLWindow2)))
    {
        TRACE("  IHTMLWindow2");
    }
    else if (IsEqualIID(riid, __uuidof(IHTMLDocument2)))
    {
        TRACE("  IHTMLDocument2");
    }
    /*else if (IsEqualIID(riid, __uuidof(IBindHost)))
    {
        trace("  IBindHost");
    }*/
    else
    {
        USES_CONVERSION;
        LPOLESTR szClsid = NULL;
        StringFromIID(riid, &szClsid);
        TRACE("  Unknown interface %ws", szClsid);
        CoTaskMemFree(szClsid);
    }
#endif
    return QueryInterface(riid, ppvObject);
}

BSTR ServiceStub::GetUrl()
{	
	TRACE("Entered ServiceStub::GetUrl");
	NPP npp = pluginInstance;
	NPObject *window;
	NPIdentifier sDocument = browserFuncs->getstringidentifier("document");
	NPVariant vDoc;

	browserFuncs->getvalue(npp, NPNVWindowNPObject, &window);

	browserFuncs->getproperty(npp, window, sDocument, &vDoc);
	browserFuncs->releaseobject(window);
	if (!NPVARIANT_IS_OBJECT(vDoc))
	{
		//return FALSE;
		//log_error("Can't get window object");
		//return NULL;
	}
	NPObject* npDoc = NPVARIANT_TO_OBJECT(vDoc);

	NPIdentifier sLocation = browserFuncs->getstringidentifier("location");
	NPVariant vLoc;
	browserFuncs->getproperty(npp, npDoc, sLocation, &vLoc);
	browserFuncs->releaseobject(npDoc);
	if (!NPVARIANT_IS_OBJECT(vLoc))
	{
		//return FALSE;
		//log_error("Can't get window.location object");
		//return NULL;
	}
	NPObject* npLoc = NPVARIANT_TO_OBJECT(vLoc);

	NPIdentifier sProperty = browserFuncs->getstringidentifier("href");
	NPVariant vProp;
	browserFuncs->getproperty(npp, npLoc, sProperty, &vProp);
	browserFuncs->releaseobject(npLoc);
	if (!NPVARIANT_IS_STRING(vProp))
	{
		//return FALSE;
		//log_error("Can't get window.location.href object");
		//return NULL;
	}
	const NPString& propValue = NPVARIANT_TO_STRING(vProp);

#if FIREFOXVER >= 36
	const NPUTF8* utfChars = propValue.UTF8Characters;
#else
	const NPUTF8* utfChars = propValue.utf8characters;
#endif
	TRACE("Exiting ServiceStub::GetUrl returning %s", utfChars);
	return _bstr_t(utfChars);
}

HRESULT STDMETHODCALLTYPE ServiceStub::QueryInterface(
                /* [in] */ REFIID riid,
                /* [iid_is][out] */ __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject)
{
	TRACE("ServiceStub::QueryInterface");
	HRESULT res = S_OK;
	if(riid == IID_IHTMLDocument2)
	{
		TRACE("IHTMLDocument2");
		*ppvObject = static_cast<IHTMLDocument2*>(this);
	}
	else if(riid == IID_IHTMLDocument)
	{
		TRACE("IHTMLDocument");
		*ppvObject = static_cast<IHTMLDocument*>(this);
	}
	else if(riid == IID_IServiceProvider)
	{
		TRACE("IServiceProvider");
		*ppvObject = static_cast<IServiceProvider*>(this);
	}
	else if(riid == IID_IDispatch)
	{
		TRACE("IDispatch");
		*ppvObject = static_cast<IDispatch*>(this);
	}
	else if(riid == IID_IUnknown)
	{
		TRACE("IUnknown");
		*ppvObject = static_cast<IDispatch*>(this);
	}
	else
	{
		TRACE("Unsupported iface");
		*ppvObject = 0;
		res = E_NOINTERFACE;
	}
	if(*ppvObject != 0)
	{
		static_cast<IUnknown*>(*ppvObject)->AddRef();
	}
	return res;
}

ULONG STDMETHODCALLTYPE ServiceStub::AddRef()
{
	TRACE("ServiceStub::AddRef");
	return ++refCount;
}

ULONG STDMETHODCALLTYPE ServiceStub::Release()
{
	TRACE("ServiceStub::Release");
	ULONG rCn = --refCount;
	if(rCn <= 0)
	{
		delete this;
	}
	return rCn;
}

HRESULT STDMETHODCALLTYPE ServiceStub::GetTypeInfoCount( 
            /* [out] */ __RPC__out UINT *pctinfo)
{
	TRACE("ServiceStub::GetTypeInfoCount");
	return E_NOTIMPL;
}
        
HRESULT STDMETHODCALLTYPE ServiceStub::GetTypeInfo(
    /* [in] */ UINT iTInfo,
    /* [in] */ LCID lcid,
    /* [out] */ __RPC__deref_out_opt ITypeInfo **ppTInfo)
{
	TRACE("ServiceStub::GetTypeInfo");
	return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE ServiceStub::GetIDsOfNames(
    /* [in] */ __RPC__in REFIID riid,
    /* [size_is][in] */ __RPC__in_ecount_full(cNames) LPOLESTR *rgszNames,
    /* [range][in] */ UINT cNames,
    /* [in] */ LCID lcid,
    /* [size_is][out] */ __RPC__out_ecount_full(cNames) DISPID *rgDispId)
{
	TRACE("ServiceStub::GetIDsOfNames");
	return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE ServiceStub::Invoke( 
    /* [in] */ DISPID dispIdMember,
    /* [in] */ REFIID riid,
    /* [in] */ LCID lcid,
    /* [in] */ WORD wFlags,
    /* [out][in] */ DISPPARAMS *pDispParams,
    /* [out] */ VARIANT *pVarResult,
    /* [out] */ EXCEPINFO *pExcepInfo,
    /* [out] */ UINT *puArgErr)
{
	TRACE("ServiceStub::Invoke");
	return E_NOTIMPL;
}
